package com.september.main;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Semaphore;

import org.apache.log4j.Logger;

import com.google.code.morphia.Datastore;
import com.google.code.morphia.Key;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import com.september.concurrent.DupsHandlerRecThread;
import com.september.concurrent.InserterThread;
import com.september.mongo.data.DataProvider;
import com.september.mongo.entities.Address;
import com.september.mongo.entities.City;
import com.september.mongo.entities.Nation;
import com.september.mongo.entities.PersonSpec;
import com.september.mongo.entities.Region;
import com.september.mongo.entities.Role;
import com.september.mongo.entities.User;


public class Runner {

	/**
	 * @param args
	 */
	private static String prefix = "files/";
	private static Semaphore sem = new Semaphore(4, true);	
	//private static Semaphore citySem = new Semaphore(4, true);	
	//private static void writeonErrorFile()

	//private InserterThread getInserterThread
	
	public static void main(String[] args) {
		//populate(args);
		//removeDups(args);
		//insertUser(args);
		testing(args);
	}
	
	private static void testing(String[] args) {
		Datastore ds = (new DataProvider()).getDatastore();
		Key<Nation> nationKey = new Key<Nation>(Nation.class, "IT");
		List<Region> regionyList = ds.find(Region.class).field("nation").equal(nationKey).asList();
		Logger.getLogger(Runner.class).debug(regionyList.size());
	}
	
	private static <T> List<T> populate(T object) {
		LinkedList<T> myList = new LinkedList<T>();
		myList.add(object);
		return myList;
	}
	
	private void signup(User user) {} 
	
	public static void insertUser(String[] args) {
		
		Datastore ds = (new DataProvider()).getDatastore();
		
		User admin = new User();
//				
//		//User admin = ds.find(User.class).field("_id").equal("theswolf").get();
//		Role role = new Role();
//		role.setRoleName("MASTER");
//		role.setDescription("Super user, it should by only one, app admin");
//		
//		ds.save(role);
		admin.setName("Christian");
		admin.setSurname("Geymonat");
    	PersonSpec mySpec = new PersonSpec();
		Address myAddress = new Address();
		myAddress.setAddress("Regione Paschetti 1");
		City garzi = ds.find(City.class).field("name").equal("Garzigliana").get();
		myAddress.setCity(garzi);
		myAddress.setZipCode("10060");
		mySpec.setAddress(populate(myAddress));
		mySpec.setMail(populate("chris.geymo@gmail.com"));
		mySpec.setTelphoneNumber(populate("3409250074"));
		admin.setSpec(mySpec);
		admin.setPrevCode("GYMCRS81P22G674W");
//		
//		
//		
		if(admin.signup("theswolf", "th3sw0lf")!= null) {
			System.out.println("signed OK!!!");
		}
		else {
			System.out.println("signing KO------!!!");
		}
		
		if(User.login("theswolf", "th3sw0lf")) {
			System.out.println("logged OK!!!");
		}
		else {
			System.out.println("logged KO------!!!");
		}
		

//		Group group = new Group();
//		group.setGroupName("MASTER");
//		group.setDescription("People in this group have MASTER role, pay attention !!!");
		//User admin = ds.find(User.class).field("_id").equal("theswolf").get();
		
		//admin.setActive(true);
		UpdateOperations<User> updateOp = ds.createUpdateOperations(User.class).set("active", true).set("master", true);
		Query<User> query = ds.find(User.class).field("_id").equal("theswolf");
		ds.update(query, updateOp);
	    admin = ds.find(User.class).field("_id").equal("theswolf").get();
		
		Role role = ds.find(Role.class).field("_id").equal("MASTER").get();
//		group.setUserList(populate(admin));
//		group.setRoles(populate(role));
//		ds.save(group);
	}
	
	public static void removeDups(String[] args) { 
		
		DataProvider provider = new DataProvider();
		Datastore ds = provider.getDatastore();
		List<Nation> nationList = ds.find(Nation.class).asList();
		
		(new DupsHandlerRecThread(nationList, Region.class, sem, "nation")).start();
		
//		for(Nation nation: nationList) {
//			List<Region> regionList = ds.find(Region.class).field("nation").equal(nation).asList();
//			new DupsHandlerRecThread<>(entityList, expectedReturn, sem, reference)
//			for(Region region:regionList) {
//				List<Province> provinceList = ds.find(Province.class).field("region").equal(region).asList();
//				(new DupsHandlerThread(provinceList, sem, citySem)).start();
//			}
//			
//		}
		
	}
	
	

	public static void populate(String[] args) {

//		Thread nationThread = new InserterThread<Nation>((new Nation()), prefix+"countryInfo.txt", sem,null);
//		Thread regionThread = new InserterThread<Region>((new Region()), prefix+"admin1CodesASCII.txt", sem, nationThread);
//		Thread provinceThread = new InserterThread<Province>((new Province()), prefix+"admin2Codes.txt", sem, regionThread);


		//nationThread.start();
		//regionThread.start();
		//provinceThread.start();
		
		
		InputStream is = 	Runner.class.getClassLoader().getResourceAsStream(prefix+"fullCountries");

		DataInputStream in = new DataInputStream(is);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String strLine;

		try {
			FileWriter fstream = new FileWriter("noReferencedCity.txt");
			BufferedWriter out = new BufferedWriter(fstream);
			int counter = 0;
			int orphan = 0;

			try {
				List<InserterThread> threadList =  new LinkedList<InserterThread>();
				while ((strLine = br.readLine()) != null)   {
					//System.out.println(strLine);
					//System.out.println("Partial: \t"+counter+"\t Orphan: \t"+orphan);
					//threadList.add(new InserterThread<City>((new City()),prefix+"fullCountries/"+strLine, sem,provinceThread));
					threadList.add(new InserterThread<City>((new City()),prefix+"fullCountries/"+strLine, sem,null));


				}

				for(Thread t : threadList) {
					t.start();
				}
			}
			catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println("Saved: \t"+counter+"\t Orphan: \t"+orphan);
			out.close();
		}

		catch (Exception e) {
			e.printStackTrace();
		}

	} 

}


